package com.newcoder.community.service;

import com.newcoder.community.dao.LoginTicketMapper;
import com.newcoder.community.dao.UserMapper;
import com.newcoder.community.entity.LoginTicket;
import com.newcoder.community.entity.User;
import com.newcoder.community.util.CommunityConstant;
import com.newcoder.community.util.CommunityUtil;
import com.newcoder.community.util.MailClient;
import com.newcoder.community.util.RedisKeyUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.processor.SpringUErrorsTagProcessor;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserService implements CommunityConstant {
    @Autowired
    private UserMapper userMapper;
//    @Autowired
//    private LoginTicketMapper loginTicketMapper;

    @Autowired
    private MailClient mailClient;
    @Autowired
    private TemplateEngine templateEngine;
    @Value("${community.path.domain}")
    private String domain;
    @Value("${server.servlet.context-path}")
    private String contextPath;
    @Autowired
    private RedisTemplate redisTemplate;
    public User findUserById(int userId){
//        return userMapper.selectById(userId);
        User user = getCache(userId);
        if(user==null){
            user = initCache(userId);
        }
        return user;
    }
    public Map<String,Object> register(User user){
        Map<String,Object> map = new HashMap<>();
        // 空值判断
        if(user==null){
            throw new IllegalArgumentException("参数不能为空");
        }
        if(StringUtils.isBlank(user.getUsername())){
            map.put("usernameMessage","账号不能为空");
            return map;
        }
        if(StringUtils.isBlank(user.getPassword())){
            map.put("passwordMessage","密码不能为空");
            return map;
        }
        if(StringUtils.isBlank(user.getEmail())){
            map.put("emailMessage","邮箱不能为空");
            return map;
        }
        //验证账号
        User u = userMapper.selectByName(user.getUsername());
        if(u!=null){
            map.put("usernameMessage","该账号以存在");
            return map;
        }
        //验证邮箱
        u= userMapper.selectByEmail(user.getEmail());
        if(u!=null){
            map.put("emailMessage","该邮箱以存在");
            return map;
        }
        //注册用户
        user.setSalt(CommunityUtil.generateUUID().substring(0,5));
        user.setPassword(CommunityUtil.md5(user.getPassword()+user.getSalt()));
        user.setType(0);
        user.setStatus(0);
        user.setActivationCode(CommunityUtil.generateUUID());
        user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png",new Random().nextInt(1000)));
        user.setCreateTime(new Date());
        userMapper.insertUser(user);
        // 发送激活邮件
        Context context = new Context();
        context.setVariable("email",user.getEmail());
        //处理处理激活邮件地址 http://localhost:8080/comminity/activation/101/code
        String url = domain+contextPath+"/activation/"+user.getId()+"/"+user.getActivationCode();
        context.setVariable("url",url);
        String content = templateEngine.process("/mail/activation",context);
        mailClient.sendMail(user.getEmail(),"激活邮件",content);

        return map;
    }
     public int activation(int userId,String code){
         User user = userMapper.selectById(userId);
         if(user==null||!user.getActivationCode().equals(code)){
             return ACTIVATION_FAILURE;
         }else if(user.getStatus()==1){
             return ACTIVATION_REPEAT;
         }else{
             userMapper.updateStatus(userId,1);
             clearCache(userId);
             return ACTIVATION_SUCCESS;
         }
     }
     public Map<String,Object> login(String username,String password, long expiredSeconds){
        Map<String,Object> map = new HashMap<>();
        //空值处理
         if(StringUtils.isBlank(username)){
             map.put("usernameMsg","账号不能为空");
             return map;
         }
         if(StringUtils.isBlank(password)){
             map.put("passwordMsg","密码不能为空");
             return map;
         }
         //对账号的合法性进行验证
         User user = userMapper.selectByName(username);
         if(user==null){
             map.put("usernameMsg","账号不存在");
             return map;
         }
         if(user.getStatus()==0){
             map.put("usernameMsg","该账号未激活");
             return map;
         }
         password = CommunityUtil.md5(password+user.getSalt());
         if(!password.equals(user.getPassword())){
             map.put("passwordMsg","密码不正确");
             return map;
         }
         //生成登录凭证
         LoginTicket loginTicket = new LoginTicket();
         loginTicket.setUserId(user.getId());
         loginTicket.setTicket(CommunityUtil.generateUUID());
         loginTicket.setStatus(0);
         loginTicket.setExpired(new Date(System.currentTimeMillis()+expiredSeconds*1000));
//         loginTicketMapper.insertLoginTicket(loginTicket);
         String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
         redisTemplate.opsForValue().set(redisKey,loginTicket);
         map.put("ticket",loginTicket.getTicket());
         return map;
     }
     public void logout(String ticket){
         String redisKey = RedisKeyUtil.getTicketKey(ticket);
         LoginTicket loginTicket = (LoginTicket)redisTemplate.opsForValue().get(redisKey);
         loginTicket.setStatus(1);
         redisTemplate.opsForValue().set(redisKey,loginTicket);
//        loginTicketMapper.updateStatus(ticket,1);
     }
     public LoginTicket findLoginTicket(String ticket){
          String redisKey = RedisKeyUtil.getTicketKey(ticket);
          return  (LoginTicket)redisTemplate.opsForValue().get(redisKey);
//        return loginTicketMapper.selectByTicket(ticket);
     }
     public int updateHeader(int userId,String url){
         int num = userMapper.updateHeader(userId, url);
         clearCache(userId);
         return num;
     }
     public int updatePassword(int userId,String password,String salt){
         password = CommunityUtil.md5(password+salt);
         int num = userMapper.updatePassword(userId, password);
         clearCache(userId);
         return num;
     }
     public User findUserByUsername(String username){
        return userMapper.selectByName(username);
     }
     //1.优先从缓存中取值
     private User getCache(int userId){
         String redisKey = RedisKeyUtil.getUserKey(userId);
         return (User) redisTemplate.opsForValue().get(redisKey);
     }
     //2.取不到初始化缓存数据
     private User initCache(int userId){
        User user = userMapper.selectById(userId);
        String redisKey = RedisKeyUtil.getUserKey(userId);
        redisTemplate.opsForValue().set(redisKey,user,3600, TimeUnit.SECONDS);
        return user;
     }
     //3.当数据变更时清除缓存数据
     private void clearCache(int userId){
         String redisKey = RedisKeyUtil.getUserKey(userId);
         redisTemplate.delete(redisKey);
     }

     public Collection<? extends GrantedAuthority> getAuthorities(int userId){
         User user = this.findUserById(userId);
         System.out.println(user.getType());
         List<GrantedAuthority> list = new ArrayList<>();
         list.add(new GrantedAuthority() {
             @Override
             public String getAuthority() {
                 switch (user.getType()) {
                     case 1:
                         return AUTHORITY_ADMIN;
                     case 2:
                         return AUTHORITY_MODERATOR;
                     default:
                         return AUTHORITY_USER;
                 }
             }
         });
         return  list;
     }
}
